import java.io.*;
import java.net.*;

public class cliente_dinamico {
  private int port_ini;
  private int nom_cliente;
  private String host;
  private SocketBytes Socket;

  private int plaza;

  // constructor
  cliente_dinamico(int port_in, int nom_in, String host_in) {
    port_ini = port_in;
    nom_cliente = nom_in;
    host = host_in;
    plaza = 0; //aun no tiene vuelo comprado
  } // cliente_dinamico

  // OJO ESPECIFICO DE CADA PROBLEMA
  private void lector() {
    int dato;

    try {
        Socket.enviaMensaje(new Integer(nom_cliente)); // Envio de identificador 
        Socket.enviaMensaje(new Integer(1)); // Indica que es lector 
        Socket.enviaMensaje(new Integer(1)); // Indica que es acceso a monitor
        Socket.enviaMensaje(new Integer(1)); // Indica que es metodo empezar_leer
        Socket.recibeMensaje(); // Espera que conteste servidor indicando que puede empezar a leer.
        // m.empezar_leer();

        Thread.sleep(500);

        Socket.enviaMensaje(new Integer(nom_cliente)); // Envio de identificador
        Socket.enviaMensaje(new Integer(1)); // Indica que es lector 
        Socket.enviaMensaje(new Integer(2)); // Indica que es acceso a base de datos
        Socket.enviaMensaje(new Integer(1)); // Indica que es metodo leer
        dato = ((Integer) Socket.recibeMensaje()).intValue(); // Recepcion de valor leido.
        // dato = bd.leer();
        System.out.println("Cliente lector " + nom_cliente + " consulta vuelo. quedan " + dato + " plazas. ");
        if (plaza > 0)
            System.out.println("Su plaza es " + plaza);
        else
            System.out.println("Aun no ha comprado");

        Socket.enviaMensaje(new Integer(nom_cliente)); // Envio de identificador
        Socket.enviaMensaje(new Integer(1)); // Indica que es lector 
        Socket.enviaMensaje(new Integer(1)); // Indica que es acceso a monitor
        Socket.enviaMensaje(new Integer(2)); // Indica que es metodo acabar_leer
        Socket.recibeMensaje(); // Espera que conteste servidor indicando que puede acabar de leer.
        // m.acabar_leer();
    } catch (Exception e) { return; }
  } // lector

  private void escritor() {
    int dato; //lee el numero de plazas que hay, decrementa y luego escribe en servidor

    try {    
        Socket.enviaMensaje(new Integer(nom_cliente)); // Envio de identificador
        Socket.enviaMensaje(new Integer(2)); // Indica que es escritor 
        Socket.enviaMensaje(new Integer(1)); // Indica que es acceso a monitor
        Socket.enviaMensaje(new Integer(3)); // Indica que es metodo empezar_escribir
        Socket.recibeMensaje(); // Espera que conteste servidor indicando que puede empezar a escribir.
        // m.empezar_escribir();
      
        Thread.sleep(1000);

        Socket.enviaMensaje(new Integer(nom_cliente)); // Envio de identificador
        Socket.enviaMensaje(new Integer(2)); // Indica que es escritor 
        Socket.enviaMensaje(new Integer(2)); // Indica que es acceso a base de datos
        Socket.enviaMensaje(new Integer(2)); // Indica que es metodo escribir

         //MODIFICADO:
        dato = ((Integer) Socket.recibeMensaje()).intValue(); //recibe el numero de plazas que hay

        if (dato > 0) {
           if (plaza > 0) //si ya se habia comprado
               System.out.println("Ha comprado otro mas");

           plaza = dato; //actualiza plaza
           dato--; //se disminuyen las plazas
           Socket.enviaMensaje(new Integer(dato)); // Indica dato a escribir
           Socket.recibeMensaje(); // Espera que conteste servidor que se ha escrito.
           // bd.escribir(dato);
           System.out.println("Cliente escritor " + nom_cliente + " compra vuelo. " + "Quedan " + dato + " plazas.\n Su plaza es: " + plaza);
        }
        else
           System.out.println("Lo sentimos, ya no quedan plazas");

        Socket.enviaMensaje(new Integer(nom_cliente)); // Envio de identificador
        Socket.enviaMensaje(new Integer(2)); // Indica que es escritor
        Socket.enviaMensaje(new Integer(1)); // Indica que es acceso a monitor
        Socket.enviaMensaje(new Integer(4)); // Indica que es metodo acabar_escribir
        Socket.recibeMensaje(); // Espera que conteste servidor indicando que puede acabar de escribir.
        // m.acabar_escribir();
    } catch (Exception e) { return; }
  } // escritor

  private void ejecutar() throws Exception{
      while (true) {  
         int opcion = 0;
         BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
         System.out.print("Introduce opcion (1: consulta, 2: reservar): ");
         try {
            opcion = Integer.parseInt(in.readLine());    
         } catch (Exception ex) {
            System.err.println("Entrada invalida");
         }
         if (opcion == 2)
            escritor();
         else
           if (opcion == 1)
              lector();
           else
              return; //introduce numero != 1, 2: salir.
      }
  } // ejecutar

  public void run() {
    try {
      // Abrimos conexion con puerto port_ini
      Socket = new SocketBytes(host, port_ini);
      System.out.println("Cliente " + nom_cliente + " ha abierto conexion con socket: puerto = " + port_ini);

      // Enviamos entero con nombre de cliente a conectar
      Socket.enviaMensaje(new Integer(nom_cliente));
      
      ejecutar();
    } catch (Exception e) // Imprimir cualquier excepcion
    { System.err.println(e); }
  } // run

  public static void main(String args[]) throws NumberFormatException {
    if (args.length != 3) {
      System.out.println("Necesito 4 argumentos: Host, Puerto Conexion y Nombre Cliente");
      System.exit(1);
    } // if ...  

    int port_ini = Integer.parseInt(args[1]);
    int nom_cliente = Integer.parseInt(args[2]);

    cliente_dinamico cd = new cliente_dinamico(port_ini, nom_cliente, args[0]);
    cd.run();
  } // main
} // cliente_dinamico
